import logging
import re

from django.conf import settings

from django import http
from django.contrib.auth import login
from django.db import DatabaseError
from django.shortcuts import redirect, render
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django_redis import get_redis_connection

from meiduo_mall.utils.response_code import RETCODE
from oauth.models import OAuthQQUser

from oauth.utils import generate_access_token, check_access_token
from users.models import User
# 创建日志输出器
logger = logging.getLogger('django')

class QQAuthURLView(View):
    """提供qq登录页面"""
    def get(self, request):
        # 接收next参数
        next = request.GET.get('next')
        # 初始化OAuthQQ对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI, state=next)
        # 生成qq登录页面
        login_url = oauth.get_qq_url()
        return http.JsonResponse({'code':RETCODE.OK, 'errmsg':'ok', 'login_url':login_url})


class QQAuthUserView(View):
    """qq登录请求的回调函数"""
    def get(self,request):
        """Oauth2.0认证"""
        # 获取code值
        code = request.GET.get('code')
        if not code:
            return http.HttpResponseForbidden('缺少code参数')
        # 创建qq登录工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                            redirect_uri=settings.QQ_REDIRECT_URI)
        try:
            # 获取access Token
            access_token = oauth.get_access_token(code)
            # 获取openID
            openid = oauth.get_open_id(access_token)
        except Exception as e:
            logger.error(e)

        try:
            oauth_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 没有绑定美多商城账号
            access_token_openid = generate_access_token(openid)
            context = {'access_token_openid': access_token_openid}
            return render(request, 'oauth_callback.html', context)

        else:
            # 如果opid已经绑定美多商城账号
            # 实现状态保持
            login(request,oauth_user.user)

            # 响应结果
            next=request.GET.get('state')
            response = redirect(next)
            response.set_cookie('username',oauth_user.user.username, max_age=3600 * 24 * 15)
            # 设置cookie
            return response

    def post(self ,request):
        """美多商城用户绑定到openid"""
        # 接收参数
        mobile = request.POST.get('mobile')
        pwd = request.POST.get('password')
        sms_code_client = request.POST.get('sms_code')
        access_token = request.POST.get('access_token_openid')

        # 校验参数
        # 判断参数是否齐全
        if not all([mobile, pwd, sms_code_client]):
            return http.HttpResponseForbidden('缺少必传参数')
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('请输入正确的手机号码')
        # 判断密码是否合格
        if not re.match(r'^[0-9A-Za-z]{8,20}$', pwd):
            return http.HttpResponseForbidden('请输入8-20位的密码')
        # 判断短信验证码是否一致
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        if sms_code_server is None:
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '无效的短信验证码'})
        if sms_code_client != sms_code_server.decode():
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '输入短信验证码有误'})

        # 判断openid是否有效；错误提示放在sms_code_errmsg位置
        openid = check_access_token(access_token)
        if not openid:
            return render(request,'oauth_callback.html', {'openid_errmsg': '无效的openid'})

        # 保存注册数据
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 用户不存在，新建用户
            user =User.objects.create_user(username=mobile,password=pwd,mobile=mobile)
        else:
            # 如果用户存在，检查用户密码
            if not user.check_password(pwd):
                return render(request,'oauth_callback.html',{'account_errmsg': '用户名或密码错误'})
        #将用户绑定openid
        try:
            oauth_qq_user = OAuthQQUser.objects.create(user=user,openid=openid)
        except DatabaseError:
            logger.error(DatabaseError)
            return render(request,'oauth_callback.html', {'qq_login_errmsg': 'QQ登录失败'})
        # 实现状态保持
        login(request,oauth_qq_user.user)
        # 响应注册结果
        next = request.GET.get('state')
        response = redirect(next)

        # 登录时用户写入到cookie，有效期15天
        response.set_cookie('username', user.username,max_age=3600 * 24 * 15)

        return response